package com.bsj.power.pls.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bsj.power.common.config.cached.PathCached;
import com.bsj.power.common.config.exception.ApiException;
import com.bsj.power.common.config.global.JsonResult;
import com.bsj.power.common.config.global.JsonResultEnum;
import com.bsj.power.common.constant.NumericalConstants;
import com.bsj.power.common.def.dto.path.PathBanDTO;
import com.bsj.power.common.def.dto.path.PathDTO;
import com.bsj.power.common.def.dto.path.PathSearchDTO;
import com.bsj.power.common.def.entity.alarmReport.AlarmReport;
import com.bsj.power.common.def.entity.gb28181.Device;
import com.bsj.power.common.def.entity.path.Path;
import com.bsj.power.common.def.entity.path.PathDevice;
import com.bsj.power.common.def.entity.path.PathPoint;
import com.bsj.power.common.def.entity.personGroup.PersonGroup;
import com.bsj.power.common.def.entity.personGroup.PersonGroupPath;
import com.bsj.power.common.def.entity.room.Room;
import com.bsj.power.common.def.vo.DeviceVO;
import com.bsj.power.common.def.vo.pls.PathVO;
import com.bsj.power.common.mapper.*;
import com.bsj.power.common.util.DataUtil;
import com.bsj.power.common.util.ParamCheckUtil;
import com.bsj.power.pls.service.PathService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.sql.Time;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author LiJiaXin
 * @version 1.0.0
 * @description PathServiceImpl
 * @time 2024/4/20 10:51
 */
@Service
public class PathServiceImpl implements PathService {

    @Resource
    private PathMapper pathMapper;

    @Resource
    private PathPointMapper pathPointMapper;

    @Resource
    private PathDeviceMapper pathDeviceMapper;

    @Autowired
    private PathCached pathCached;

    @Resource
    private DeviceMapper deviceMapper;

    @Resource
    private PersonGroupPathMapper personGroupPathMapper;

    @Resource
    private RoomMapper roomMapper;

    @Resource
    private AlarmReportMapper alarmReportMapper;

    /**
     * 添加围栏
     *
     * @param pathDTO
     * @return com.bsj.power.common.config.global.JsonResult
     * @author ljx
     * @time 2024/4/20 11:59
     */
    @Override
    @Transactional
    public JsonResult addPath(PathDTO pathDTO) {
        checkIsExist(pathDTO);
        Path path = new Path();
        BeanUtils.copyProperties(pathDTO, path);
        path.setBeginTime(Time.valueOf(pathDTO.getBeginTime()));
        path.setEndTime(Time.valueOf(pathDTO.getEndTime()));
        if (pathMapper.insert(path) > NumericalConstants.ZERO) {
            // 添加位置点
            addPathPoint(pathDTO.getPathPoints(), path, pathDTO.getDeviceIds());
            return JsonResult.success();
        } else {
            return JsonResult.fail();
        }
    }

    /**
     * 删除围栏
     *
     * @param pathId
     * @return com.bsj.power.common.config.global.JsonResult
     * @author ljx
     * @time 2024/4/20 12:00
     */
    @Override
    @Transactional
    public JsonResult deletePath(Integer pathId) {
        ParamCheckUtil.isNull(pathId);
        ParamCheckUtil.isNull(pathMapper.selectById(pathId), JsonResultEnum.PATH_NOT_EXIST);
        if (personGroupPathMapper.exists(Wrappers.<PersonGroupPath>lambdaQuery().eq(PersonGroupPath::getPathId, pathId))) {
            return JsonResult.fail(JsonResultEnum.PATH_BINDING_PERSON_GROUP);
        }
        // TODO 围栏下有视频设备的情况不能删除
        if (pathMapper.deleteById(pathId) > NumericalConstants.ZERO) {
            // 删除位置点
            pathPointMapper.delete(Wrappers.<PathPoint>lambdaQuery().eq(PathPoint::getPathId, pathId));
            pathCached.hdelPathInfo(pathId);
            //删除关联的视频ID信息
            pathDeviceMapper.delete(Wrappers.<PathDevice>lambdaQuery().eq(PathDevice::getPathId, pathId));
            pathCached.delPathDevice(pathId);
            //甲方要求删除围栏时删除围栏报警相关的数据
            alarmReportMapper.delete(new QueryWrapper<AlarmReport>().lambda().eq(AlarmReport::getPathId, pathId));
            return JsonResult.success();
        } else {
            return JsonResult.fail();
        }
    }

    /**
     * 修改围栏
     *
     * @param pathDTO
     * @return com.bsj.power.common.config.global.JsonResult
     * @author ljx
     * @time 2024/4/20 12:00
     */
    @Override
    @Transactional
    public JsonResult updatePath(PathDTO pathDTO) {
        Integer pathId = pathDTO.getPathId();
        ParamCheckUtil.isNull(pathId);
        ParamCheckUtil.isNull(pathMapper.selectById(pathId), JsonResultEnum.PATH_NOT_EXIST);
        checkIsExist(pathDTO);
        Path path = new Path();
        BeanUtils.copyProperties(pathDTO, path);
        path.setBeginTime(Time.valueOf(pathDTO.getBeginTime()));
        path.setEndTime(Time.valueOf(pathDTO.getEndTime()));

        LambdaUpdateWrapper<Path> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(Path::getPathId, pathId);
        if (StringUtils.isBlank(path.getRoomNo())) {
            updateWrapper.set(Path::getRoomNo, null);
        }
        if (pathMapper.update(path, updateWrapper) > NumericalConstants.ZERO) {
            // 修改位置点
            pathPointMapper.delete(Wrappers.<PathPoint>lambdaQuery().eq(PathPoint::getPathId, pathId));
            List<Long> deviceIds = pathDTO.getDeviceIds();
            if (deviceIds != null && !deviceIds.isEmpty()) {
                pathDeviceMapper.deleteById(pathId);
                pathCached.delPathDevice(pathId);
            }
            addPathPoint(pathDTO.getPathPoints(), path, deviceIds);
            return JsonResult.success();
        } else {
            return JsonResult.fail();
        }
    }

    /**
     * 获取单个围栏
     *
     * @param pathId
     * @return com.bsj.power.common.def.vo.pls.PathVO
     * @author ljx
     * @time 2024/4/20 12:00
     */
    @Override
    public PathVO getPathById(Integer pathId) {
        ParamCheckUtil.isNull(pathId);
        Path path = pathMapper.selectById(pathId);
        List<PathDevice> pathDevices = pathDeviceMapper.selectList(Wrappers.<PathDevice>lambdaQuery().eq(PathDevice::getPathId, path.getPathId()));
        ParamCheckUtil.isNull(path, JsonResultEnum.PATH_NOT_EXIST);
        PathVO pathVO = new PathVO();
        BeanUtils.copyProperties(path, pathVO);
        if (!pathDevices.isEmpty()) {
            pathVO.setDeviceIds(pathDevices.stream().map(PathDevice::getDeviceId).collect(Collectors.toList()));
        }
        pathVO.setBeginTime(path.getBeginTime().toString());
        pathVO.setEndTime(path.getEndTime().toString());
        pathVO.setPathPoints(pathPointMapper.selectList(Wrappers.<PathPoint>lambdaQuery().eq(PathPoint::getPathId, pathId)));
        return pathVO;
    }

    /**
     * 围栏分页
     *
     * @param pathSearchDTO
     * @return com.bsj.power.common.config.global.JsonResult<java.util.List < com.bsj.power.common.def.vo.pls.PathVO>>
     * @author ljx
     * @time 2024/4/20 12:00
     */
    @Override
    public JsonResult<List<PathVO>> pagePath(PathSearchDTO pathSearchDTO) {
        List<PathVO> pathVOS = pathMapper.pagePath(pathSearchDTO);
        if (CollectionUtils.isEmpty(pathVOS)) {
            return JsonResult.success(pathVOS, NumericalConstants.ZERO);
        }
        List<PathVO> result = DataUtil.pagingByList(pathVOS, pathSearchDTO.getPageSize(), pathSearchDTO.getPageNumber());
        //        Page<Path> page = new Page<>(pathSearchDTO.getPageNumber(), pathSearchDTO.getPageSize());
//        QueryWrapper<Path> queryWrapper = new QueryWrapper<>();
//        String pathName = pathSearchDTO.getPathName();
//        if (StringUtils.isNotBlank(pathName)) {
//            queryWrapper.eq("path_name", pathName);
//        }
//        IPage<Path> iPage = pathMapper.selectPage(page, queryWrapper);
//        List<Path> paths = iPage.getRecords();
//        long total = iPage.getTotal();
//        if (total == NumericalConstants.ZERO) {
//            return JsonResult.success(pathVOS, total);
//        }
//        pathVOS = paths.stream().map(path -> {
//            PathVO pathVO = new PathVO();
//            BeanUtils.copyProperties(path, pathVO);
//            pathVO.setBeginTime(path.getBeginTime().toString());
//            pathVO.setEndTime(path.getEndTime().toString());
//            pathVO.setCreateTime(DateUtil.formatDateTime(path.getCreateTime()));
//            pathVO.setUpdateTime(DateUtil.formatDateTime(path.getUpdateTime()));
//            return pathVO;
//        }).collect(Collectors.toList());
        result.stream().forEach(item -> {
            List<PathDevice> pathDevices = pathDeviceMapper.selectList(Wrappers.<PathDevice>lambdaQuery().eq(PathDevice::getPathId, item.getPathId()));
            if (pathDevices != null && !pathDevices.isEmpty()) {
                List<Long> collect = pathDevices.stream().map(PathDevice::getDeviceId).collect(Collectors.toList());
                item.setDeviceIds(collect);
            }
        });
        return JsonResult.success(result, pathVOS.size());
    }

    /**
     * 根据围栏id查询视频设备信息
     *
     * @param pathId
     * @return java.util.List<com.bsj.power.common.def.vo.DeviceVO>
     * @author ljx
     * @time 2024/9/18 14:39
     */
    @Override
    public List<DeviceVO> getVideoDevicesByPathId(Integer pathId) {
        ParamCheckUtil.isNull(pathId);
        Path path = pathMapper.selectById(pathId);
        ParamCheckUtil.isNull(path, JsonResultEnum.PATH_BE_DELETED);
        List<PathDevice> pathDevices = pathDeviceMapper.selectList(Wrappers.<PathDevice>lambdaQuery().eq(PathDevice::getPathId, pathId));
        ParamCheckUtil.isEmpty(pathDevices, JsonResultEnum.PATH_NO_BINDING_VIDEO_DEVICE);
        List<Long> deviceIds = pathDevices.stream().map(PathDevice::getDeviceId).collect(Collectors.toList());
        List<Device> devices = deviceMapper.selectList(Wrappers.<Device>lambdaQuery().in(Device::getId, deviceIds));
        ParamCheckUtil.isEmpty(devices, JsonResultEnum.PATH_NO_BINDING_VIDEO_DEVICE);
        return devices.stream().map(device -> {
            DeviceVO deviceVO = new DeviceVO();
            BeanUtils.copyProperties(device, deviceVO);
            return deviceVO;
        }).collect(Collectors.toList());
    }

    /**
     * 是否禁用
     *
     * @param pathBanDTO
     * @return com.bsj.power.common.config.global.JsonResult
     * @author ljx
     * @time 2024/12/28 12:06
     */
    @Override
    public JsonResult isBan(PathBanDTO pathBanDTO) {
        Integer isBan = pathBanDTO.getIsBan();
        List<Integer> pathIds = pathBanDTO.getPathIds();
        if (pathMapper.isBan(pathBanDTO) > NumericalConstants.ZERO) {
            List<Path> paths = pathCached.hgetPathInfoByIds(pathIds);
            if (!CollectionUtils.isEmpty(paths)) {
                paths.forEach(path -> {
                    path.setIsBan(isBan);
                    pathCached.hsetPathInfo(path);
                });
            }
        }
        return JsonResult.success();
    }

    /**
     * 围栏名称是否存在
     *
     * @param pathDTO
     * @return void
     * @author ljx
     * @time 2024/4/26 15:41
     */
    private void checkIsExist(PathDTO pathDTO) {
        QueryWrapper<Path> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("path_name", pathDTO.getPathName());
        Integer pathId = pathDTO.getPathId();
        if (pathId != null) {
            queryWrapper.ne("path_id", pathId);
        }
        if (pathMapper.exists(queryWrapper)) {
            throw new ApiException(JsonResultEnum.PATH_EXIST);
        }
        String roomNo = pathDTO.getRoomNo();
        if (StringUtils.isNotBlank(roomNo)) {
            if (!roomMapper.exists(Wrappers.<Room>lambdaQuery().eq(Room::getRoomNo, roomNo))) {
                throw new ApiException(JsonResultEnum.ROOM_NOT_EXIST);
            }
        }
    }

    /**
     * 添加位置点
     *
     * @param pathPoints
     * @param path
     * @return void
     * @author ljx
     * @time 2024/4/26 20:00
     */
    private void addPathPoint(List<PathPoint> pathPoints, Path path, List<Long> devices) {
        Integer pathId = path.getPathId();
        for (PathPoint pathPoint : pathPoints) {
            pathPoint.setPathId(pathId);
        }
        pathPointMapper.batchInsert(pathPoints);
        path.setPathPoints(pathPoints);
        pathCached.hsetPathInfo(path);
        if (devices != null && !devices.isEmpty()) {
            List<PathDevice> pathDevices = new ArrayList<>();
            //关联视频设备
            devices.stream().forEach(item -> {
                PathDevice pathDevice = new PathDevice();
                pathDevice.setPathId(pathId);
                pathDevice.setDeviceId(item);
                pathDevices.add(pathDevice);
            });
            pathDeviceMapper.batchInsert(pathDevices);
            pathCached.saddPathDevice(pathId, devices);
        }
    }

}
